#-*- python -*-
import os
import os.path

AddOption('--test',
          action='store_true',
          dest='test',
          help='test')
AddOption('--update',
          action='store_true',
          dest='update',
          help='update')
AddOption('--strict',
          action='store_true',
          dest='strict',
          help='strict')

def generate_bison_action(source, target, env, for_signature):
    def arguments(target):
        target = str(target)
        root, ext = os.path.splitext(target)
        if ext == '.c':
            return '--output=' + target
        if ext == '.h':
            return '--defines=' + target
        return '--output=' + target

    target = ' '.join(map(arguments, target))
    return '$YACC $YACCFLAGS %s %s' % (target, source[0])

def generate_flex_action(source, target, env, for_signature):
    def arguments(target):
        target = str(target)
        root, ext = os.path.splitext(target)
        if ext == '.c':
            return '--outfile=' + target
        if ext == '.h':
            return '--header-file=' + target
        return '--outfile=' + target

    target = ' '.join(map(arguments, target))
    return '$LEX $LEXFLAGS %s %s' % (target, source[0])

def generate_cat_action(source, target, env, for_signature):
    source = map(lambda x: str(x), source)
    target = str(target[0])
    return 'cat %s > %s' % (' '.join(source), target)

def generate_compc_action(source, target, env, for_signature):
    def arguments(source):
        source = str(source)
        root, ext = os.path.splitext(source)
        if ext == '.swc':
            return '-library-path+=' + source
        if ext == '.as':
            return '-include-sources ' + source
        else:
            return '-include-sources ' + source
        
    source = ' '.join(map(arguments, source))
    return 'compc -warnings=true -optimize=true -debug=false -strict=true -omit-trace-statements=true -target-player 10.0.0 %s -output %s' % (source, target[0])

bison = Builder(generator=generate_bison_action)
flex = Builder(generator=generate_flex_action)
cat = Builder(generator=generate_cat_action)
compc = Builder(generator=generate_compc_action)
cpp = Builder(action='cpp -Wall -nostdinc -P -I. $SOURCE $TARGET')
haxe = Builder(action='haxe $SOURCE')

cflags = Split('-Wall -Wextra -pedantic -DNDEBUG -O3 -fmerge-all-constants -funsafe-loop-optimizations -fweb') + Split('-fwhole-program -combine')
linkflags = Split('-O3')

kw = {'YACCFLAGS': '-Wall --no-lines',
      'LEXFLAGS': Split('--verbose --perf-report') + Split(' --noline'),
      'CFLAGS': cflags,
      'LINKFLAGS': linkflags,
      'BUILDERS': {'Bison': bison,
                   'Flex': flex,
                   'Cat': cat,
                   'Compc': compc,
                   'Cpp': cpp,
                   'Haxe': haxe}}

bson_source = ['buf.c', 'bson.c']


if GetOption('strict'):
    parser_y = 'strict-parser.y'
    lexer_l = 'strict-lexer.l'
else:
    parser_y = 'parser.y'
    lexer_l = 'lexer.l'

if GetOption('test'):
    env = Environment(**kw)

    parser = env.Bison(['parser.c', 'parser-defines.h'], parser_y)
    
    lexer = env.Flex(['lexer.c', 'lexer-defines.h'], lexer_l)

    cson_c = env.Cat('cson.c', ['lexer.c', 'parser.c', 'main.c'] + bson_source)
    env.Program('bson', cson_c)

else:
    alchemy_home = Dir(os.environ['ALCHEMY_HOME'])
    alchemy_ver = os.environ['ALCHEMY_VER']
    path = ':'.join([str(alchemy_home.Dir('achacks')), os.environ['PATH']])
    asc = File(os.environ['ASC'])
    swfbridge = File(os.environ['SWFBRIDGE'])

    alchemy_gcc = alchemy_home.File('achacks/gcc')
    alchemy_include = alchemy_home.Dir('avm2-libc/include')

    alchemy_env = {'ALCHEMY_HOME': alchemy_home,
                   'ALCHEMY_VER': alchemy_ver,
                   'PATH': path,
                   'ASC': asc,
                   'SWFBRIDGE': swfbridge,
                   'ACHACKS_TMP': 1}

    alchemy_cpppath = alchemy_include

    alchemy_linkflags = linkflags + Split('-swc')

    alchemy_cflags = cflags + Split('-nostdinc -emit-llvm')

    alchemy_kw = dict(kw)
    alchemy_kw['ENV'] = alchemy_env
    alchemy_kw['CC'] = alchemy_gcc
    alchemy_kw['CFLAGS'] = alchemy_cflags
    alchemy_kw['CPPPATH'] = alchemy_cpppath
    alchemy_kw['LINKFLAGS'] = alchemy_linkflags

    env = Environment(**alchemy_kw)
    
    parser = env.Bison(['parser.c', 'parser-defines.h'], parser_y)

    lexer = env.Flex(['lexer.c', 'lexer-defines.h'], lexer_l)

    cson_c = env.Cat('cson.c', ['lexer.c', 'parser.c', 'json.c'] + bson_source)
    env.Depends(cson_c, [parser, lexer])

    cson_swc = env.Program('cson.swc', cson_c)
    env.Depends(cson_swc, cson_c)
    env.Clean(cson_swc, [Glob('*.exe'), Glob('*.abc'), Glob('*.bc'), Glob('*.achacks.*')])
    
    abstract_decoder = env.Cpp('com/rational/serialization/json/AbstractDecoder.hx',
                               'com/rational/serialization/json/AbstractDecoder.chx')
    decoder = env.Cpp('com/rational/serialization/json/Decoder.hx',
                      'com/rational/serialization/json/Decoder.chx')
    typed_decoder = env.Cpp('com/rational/serialization/json/TypedDecoder.hx',
                            'com/rational/serialization/json/TypedDecoder.chx')
    env.Depends([abstract_decoder, decoder, typed_decoder], 'tag.h')
    
    hson_swc = env.Haxe('hson.swc', 'build.hxml')
    env.Depends(hson_swc, [abstract_decoder, decoder, typed_decoder])
    
    if GetOption('update'):
        env.Command('com/adobe/serialization/json/JSONEncoder.as',
                    'com/rational/serialization/json/JSON.as',
                    'svn checkout http://as3corelib.googlecode.com/svn/trunk/src/com/adobe/serialization/json com/adobe/serialization/json')
    
    json = env.Compc('json.swc', [cson_swc, hson_swc,
                                  'com/adobe/serialization/json/JSONEncoder.as',
                                  'com/rational/serialization/json/JSON.as',
                                  'com/rational/serialization/json/JSONError.as',
                                  'com/rational/serialization/json/Reference.as'])
    if GetOption('update'):
        env.Command(['tests/com/adobe/serialization/json/JSONTest.as',
                     'tests/com/adobe/serialization/json/SimpleClass.as'],
                    [json, 'tests/JSONTest.patch'],
                    ['svn checkout http://as3corelib.googlecode.com/svn/trunk/tests/src/com/adobe/serialization/json tests/com/adobe/serialization/json',
                     'patch -d tests -p0 com/adobe/serialization/json/JSONTest.as JSONTest.patch'])
